
import java.util.regex.*;
import java.util.ArrayList;
import java.sql.*;

public class User {
  //Attributs

  private int idUser;
  private String nom;
  private String mail;
  private static final String tableUser = "ap4_sp_user";

  //Constructeur
  public User(String nom, String mail) throws IllegalArgumentException, SQLException {
    try {
      verif(nom, mail);
      this.nom = nom;
      this.mail = mail;
      this.createUser();
    } catch (IllegalArgumentException e) {
      throw e;
    }
  }

  public User(int idUser, String nom, String mail) {
    this.idUser = idUser;
    this.nom = nom;
    this.mail = mail;
  }

  //Accesseurs
  public String getNom() {
    return this.nom;
  }

  public void setNom(String nom) throws IllegalArgumentException, SQLException {
    boolean exist;
    try {
      exist = User.existNom(nom);
    } catch (SQLException e) {
      throw e;
    }

    if (nom.length() > 50 || nom.length() < 1) {
      throw new IllegalArgumentException("La taille maximum du nom est de 50 caractères et la taille minimum est de 1 caractère.");
    } else {
      if (exist) {
        throw new IllegalArgumentException("Le nom que vous avez entré existe déjà dans la base de donnée");
      } else {
        this.nom = nom;
        //Modification dans la BDD
        try {
          bdd db = bdd.getInstance();
          db.update("UPDATE " + tableUser + " SET nom='" + nom + "' WHERE idUser=" + this.idUser);
        } catch (SQLException e) {
          throw e;
        }
      }
    }
  }

  public String getMail() {
    return this.mail;
  }

  public void setMail(String mail) throws IllegalArgumentException, SQLException {
    boolean exist;
    try {
      exist = User.existMail(mail);
    } catch (SQLException e) {
      throw e;
    }
    if (exist) {
      throw new IllegalArgumentException("Le mail que vous avez entré existe déjà dans la base de données");
    } else {
      if (Pattern.matches("(\\w+)@(\\w+\\.)(\\w+)(\\.\\w+)?", mail)) {
        this.mail = mail;
        //Modification dans la BDD
        try {
          bdd db = bdd.getInstance();
          db.update("UPDATE " + tableUser + " SET mail='" + mail + "' WHERE idUser=" + this.idUser);
        } catch (SQLException e) {
          throw e;
        }
      } else {
        throw new IllegalArgumentException("Le mail que vous avez entré est invalide");
      }
    }
  }

  public int getId() {
    return this.idUser;
  }

  public String toString() {
    return "User{" + "idUser=" + idUser + "nom=" + nom + "mail=" + mail + '}';
  }

  //Methodes
  private void verif(String nom, String mail) throws IllegalArgumentException, SQLException {
    verifNom(nom);
    verifMail(mail);
  }

  public static void verifMail(String mail) throws IllegalArgumentException, SQLException {
    boolean exist;
    try {
      exist = User.existMail(mail);
    } catch (SQLException e) {
      throw e;
    }
    if (exist) {
      throw new IllegalArgumentException("Le mail que vous avez entré existe déjà dans la base de données");
    }
    if (!(Pattern.matches("(\\w+)@(\\w+\\.)(\\w+)(\\.\\w+)?", mail))) {
      throw new IllegalArgumentException("Le mail que vous avez entré est invalide");
    }
  }

  public static void verifNom(String nom) throws IllegalArgumentException, SQLException {
    boolean exist;
    try {
      exist = User.existNom(nom);
    } catch (SQLException e) {
      throw e;
    }
    if (exist) {
      throw new IllegalArgumentException("L'utilisateur existe déjà dans la base de données.");
    }
    if (nom.length() > 50 || nom.length() < 1) {
      throw new IllegalArgumentException("La taille maximum du nom est de 50 caractères et la taille minimum est de 1 caractère.");
    }
  }

  @Override
  public boolean equals(Object obj) {
    User user;
    if (obj.getClass() == this.getClass()) {
      user = (User) obj;
      if (this.nom.equals(user.nom) && this.mail.equals(user.mail)) {
        return true;
      }
    }
    return false;
  }

  public static boolean existId(int id) throws SQLException {
    try {
      bdd db = bdd.getInstance();
      ResultSet res = db.req("SELECT * FROM " + tableUser + " WHERE idUser ='" + id + "'");
      return res.first();
    } catch (SQLException e) {
      throw e;
    }
  }

  public static boolean existNom(String nom) throws SQLException {
    try {
      bdd db = bdd.getInstance();
      ResultSet res = db.req("SELECT * FROM " + tableUser + " WHERE nom ='" + nom + "'");
      return res.first();
    } catch (SQLException e) {
      throw e;
    }
  }

  public static boolean existMail(String mail) throws SQLException {
    try {
      bdd db = bdd.getInstance();
      ResultSet res = db.req("SELECT * FROM " + tableUser + " WHERE mail ='" + mail + "'");
      return res.first();
    } catch (SQLException e) {
      throw e;
    }
  }

  public void createUser() throws SQLException {
    try {
      bdd db = bdd.getInstance();
      db.update("INSERT INTO " + tableUser + " (nom, mail) VALUES ('" + this.nom + "','" + this.mail + "')");
      this.idUser = this.getLastId();
    } catch (SQLException e) {
      throw e;
    }
  }

  private int getLastId() throws SQLException {
    try {
      bdd db = bdd.getInstance();
      ResultSet res = db.req("SELECT idUser FROM " + tableUser + " ORDER BY idUser DESC LIMIT 0,1");
      res.first();
      return res.getInt(1) + 1;
    } catch (SQLException e) {
      throw e;
    }
  }

  public void delete() throws SQLException {
    try {
      bdd db = bdd.getInstance();
      db.update("DELETE FROM  " + tableUser + " WHERE idUser=" + this.idUser);
    } catch (SQLException e) {
      throw e;
    }
  }

  public static ArrayList<User> chargerUsers() throws SQLException {
    ArrayList users = new ArrayList<User>();
    try {
      bdd db = bdd.getInstance();
      ResultSet res = db.req("SELECT * FROM " + tableUser + " ORDER BY idUser DESC");
      while (res.next()) {
        users.add(new User(res.getInt("idUser"), res.getString("nom"), res.getString("mail")));
      }
      return users;
    } catch (SQLException e) {
      throw e;
    }
  }

  public static User getUser(int id, ArrayList<User> users) {
    for (User user : users) {
      if (user.getId() == id) {
        return user;
      }
    }
    return null;
  }

  public static User getUser(String nom) throws SQLException {
    ArrayList<User> users;
    try {
      users = chargerUsers();
    } catch (SQLException e) {
      throw e;
    }
    for (User user : users) {
      if (user.getNom().equals(nom)) {
        return user;
      }
    }
    return null;
  }
}